package sharetime.core.pager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("unchecked")
public class MergedListPager implements Pager {
	public static final Logger logger = LoggerFactory
			.getLogger(MergedListPager.class);

	private List pagers;

	private int combinedIndex;

	public Pager currentPager;

	private List currentPage;

	private int indexOfFirstItemInCurrentPage;

	private boolean onLastPage;

	private class MergedListIterator implements Iterator {
		private List iterators;

		@SuppressWarnings("unchecked")
		public MergedListIterator(List listOfPagers) {
			iterators = new ArrayList();
			Pager pager;
			for (Iterator i = listOfPagers.iterator(); i.hasNext(); iterators
					.add(pager.iterator()))
				pager = (Pager) i.next();
		}

		private Iterator getCurrentIterator() {
			for (int i = 0; i < iterators.size(); i++) {
				Iterator iterator = (Iterator) iterators.get(i);
				if (iterator.hasNext())
					return iterator;
			}

			return Collections.EMPTY_LIST.iterator();
		}

		public void remove() {
			throw new UnsupportedOperationException(
					"This iterator does not support removal");
		}

		public boolean hasNext() {
			return getCurrentIterator().hasNext();
		}

		public Object next() {
			Object nextElement = getCurrentIterator().next();
			if (!hasNext())
				onLastPage = true;
			return nextElement;
		}
	}

	@SuppressWarnings("unchecked")
	MergedListPager(List pagers) {
		onLastPage = false;
		this.pagers = pagers;
	}

	@SuppressWarnings("unchecked")
	public boolean isEmpty() {
		for (Iterator iter = pagers.iterator(); iter.hasNext();) {
			Pager pager = (Pager) iter.next();
			if (!pager.isEmpty())
				return false;
		}

		return true;
	}

	@SuppressWarnings("unchecked")
	public Iterator iterator() {
		if (pagers == null)
			return Collections.EMPTY_LIST.iterator();
		else
			return new MergedListIterator(pagers);
	}

	@SuppressWarnings("unchecked")
	public List getCurrentPage() {
		if (currentPage == null) {
			currentPage = new ArrayList();
			indexOfFirstItemInCurrentPage = combinedIndex;
			for (Iterator iterator = iterator(); iterator.hasNext()
					&& currentPage.size() < 100;) {
				currentPage.add(iterator.next());
				combinedIndex++;
			}

			if (currentPage.size() < 100 || !iterator().hasNext())
				onLastPage = true;
		}
		return currentPage;
	}

	public void nextPage() {
		try {
			skipTo(combinedIndex + (currentPage != null ? 0 : 100));
		} catch (PagerException e) {
			logger.error("Erroring calling nextPage()", e);
		}
	}

	public boolean onLastPage() {
		return onLastPage;
	}

	public void skipTo(int index) throws PagerException {
		if (index < combinedIndex)
			throw new PagerException("Cannot run the index back to [" + index
					+ "] from [" + combinedIndex + "]");
		for (; combinedIndex < index; combinedIndex++)
			iterator().next();

		currentPage = null;
		getCurrentPage();
	}

	public int getIndex() {
		return combinedIndex;
	}

	public int getIndexOfFirstItemInCurrentPage() {
		getCurrentPage();
		return indexOfFirstItemInCurrentPage;
	}

}
